package com.itheima.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.github.miemiedev.mybatis.paginator.dialect.H2Dialect;
import com.itheima.service.MemberService;
import com.itheima.service.OrderService;
import com.itheima.service.ReportService;
import com.itheima.service.SetmealService;
import constant.MessageConstant;
import entity.Result;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import pojo.Member;
import pojo.Setmeal;
import utils.DateUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 统计报表
 */
@RestController
@RequestMapping("/report")
public class ReportController {
    
    @Reference
    private MemberService memberService;
    @Reference
    private SetmealService setmealService;
    @Reference
    private OrderService orderService;
    @Reference
    private ReportService reportService;
    
    /**
     * 过去一年时间内 ,每个月**的会员总数据量
     */
    @RequestMapping("/getMemberReport")
    public Result getMemberReport(){
        try{
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MONTH,-12);//日历时间改为当前时间减去12个月
    
            List<String> months = new ArrayList<>();
    
            for(int i = 0; i < 12; i++){
                calendar.add(Calendar.MONTH,1);//日历时间改为当前时间加一个月
                months.add(new SimpleDateFormat("yyyy-MM").format(calendar.getTime()));
            }
            System.out.println(months);
            //[2021-10, 2021-11, 2021-12, 2022-01, 2022-02, 2022-03, 2022-04, 2022-05, 2022-06, 2022-07, 2022-08, 2022-09]
    
            Map<String,Object> map = new HashMap<>();
            map.put("months",months);//月份列表
            
            System.out.println("月份列表:" + map.get("months"));
            
            //根据月份列表查询每月份的会员数量，返回list
            List<Integer> memberCount = memberService.findMemberCountsListByRegTimes(months);
            map.put("memberCount",memberCount);//会员数量列表 []
            
            System.out.println("会员数量列表:" + map.get("memberCount"));
            
            return new Result(true, MessageConstant.GET_MEMBER_NUMBER_REPORT_SUCCESS,map);
        }catch (Exception e){
            e.printStackTrace();
            return new Result(false, MessageConstant.GET_MEMBER_NUMBER_REPORT_FAIL);
        }
    }
    
    /**
     * 套餐占比统计表，进行套餐名字和套餐数种类预约的数量
     */
    @RequestMapping("/getSetmealReport")
    public Result getSetmealReport(){
        try {
            //定义setmealCount，需要返回给前端
            //定义setmealNames，需要返回给前端
            //定义setmealCount和setmealNames不能包装成pojo对象，那就返回一个Map对象
            Map<String,Object> map = new HashMap<>();
        
            //根据要求，setmealCount需要的json格式是数组，数组里面放n个对象
            List<Map<String,Integer>> setmealCount = setmealService.findCountWithName();
        
            map.put("setmealCount",setmealCount);
        
            //根据要求，setmealNames需要的json格式是数组
            List<String> setmealNames =new ArrayList<>();
        
            for (Map<String, Integer> m : setmealCount) {
                String name = String.valueOf(m.get("name"));
                setmealNames.add(name);
            }
            map.put("setmealNames",setmealNames);
            return new Result(true,MessageConstant.GET_SETMEAL_COUNT_REPORT_SUCCESS,map);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(true,MessageConstant.GET_SETMEAL_COUNT_REPORT_FAIL);
        }
    
    }
    
    /**
     * 运营数据统计,统计报表
     */
    @RequestMapping("/getBusinessReportData")
    public Result getBusinessReportData(){
        try {
            //所有数据封装在Map
            Map<String,Object> map = reportService.getBusinessReport();
            String s = (String) map.get("reportDate");
            System.out.println("s================" + s);
            return new Result(true,MessageConstant.GET_BUSINESS_REPORT_SUCCESS,map);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false,MessageConstant.GET_BUSINESS_REPORT_FAIL);
        }
    }
    
    /**
     * 导出excel文件，将前端信息（运营数据统计信息）通过POI导出到Excel中
     */
    @RequestMapping("/exportBusinessReport")
    public Result exportBusinessReport(HttpServletRequest request, HttpServletResponse response){
        try {
            Map<String, Object> report = reportService.getBusinessReport();
            //取出报表数据，写入到Excel
            String reportDate = (String) report.get("reportDate");//日期
            Integer todayNewMember = (Integer) report.get("todayNewMember");//今日新增会员数
            Integer totalMember = (Integer) report.get("totalMember");//总会员数
            Integer thisWeekNewMember = (Integer) report.get("thisWeekNewMember");//本周新增会员数
            Integer thisMonthNewMember = (Integer) report.get("thisMonthNewMember");//本月新增会员数
            Integer todayOrderNumber = (Integer) report.get("todayOrderNumber");//今日预约数
            Integer todayVisitsNumber = (Integer) report.get("todayVisitsNumber");//今日到诊数
            Integer thisWeekOrderNumber = (Integer) report.get("thisWeekOrderNumber");//本周预约数
            Integer thisWeekVisitsNumber = (Integer) report.get("thisWeekVisitsNumber");//本周到诊数
            Integer thisMonthOrderNumber = (Integer) report.get("thisMonthOrderNumber");//本月预约数
            Integer thisMonthVisitsNumber = (Integer) report.get("thisMonthVisitsNumber");//本月到诊数
            List<Map> hotSetmeal = (List<Map>) report.get("hotSetmeal");//热门套餐，前四名
            
            //获取Excel文件绝对路径
            String realPath = request.getSession().getServletContext().getRealPath("template");
            System.out.println("realPath=======" + realPath);
            realPath = request.getSession().getServletContext().getRealPath("template") + File.separator + "report_template.xlsx";
    
            //创建工作簿
            XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(new File(realPath)));
            //创建表
            XSSFSheet sheet = workbook.getSheetAt(0);
            //在行内插入数据
            sheet.getRow(2).getCell(5).setCellValue(reportDate);//日期
            sheet.getRow(4).getCell(5).setCellValue(todayNewMember);//今日新增会员数
            sheet.getRow(4).getCell(7).setCellValue(totalMember);//总会员数
            sheet.getRow(5).getCell(5).setCellValue(thisWeekNewMember);//本周新增会员数
            sheet.getRow(5).getCell(7).setCellValue(thisMonthNewMember);//本月新增会员数
            sheet.getRow(7).getCell(5).setCellValue(todayOrderNumber);//今日预约数
            sheet.getRow(7).getCell(7).setCellValue(todayVisitsNumber);//今日到诊数
            sheet.getRow(8).getCell(5).setCellValue(thisWeekOrderNumber);//本周预约数
            sheet.getRow(8).getCell(7).setCellValue(thisWeekVisitsNumber);//本周到诊数
            sheet.getRow(9).getCell(5).setCellValue(thisMonthOrderNumber);//本月预约数
            sheet.getRow(9).getCell(7).setCellValue(thisMonthVisitsNumber);//本月到诊数
    
            int rowNum = 12;
            for (Map map : hotSetmeal) {
                String name = (String) map.get("name");
                Long setmeal_count = (Long) map.get("setmeal_count");
                BigDecimal proportion = (BigDecimal) map.get("proportion");
                sheet.getRow(rowNum).getCell(4).setCellValue(name);//套餐名称
                sheet.getRow(rowNum).getCell(5).setCellValue(setmeal_count);//预约数量
                sheet.getRow(rowNum++).getCell(6).setCellValue(proportion.doubleValue());//占比
                //sheet.getRow(12).getCell(7).setCellValue(totalMember);//备注
            }
    
            //通过输出流进行文件下载(下载弹框响应给前端)
            ServletOutputStream out = response.getOutputStream();
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("content-Disposition", "attachment;filename=report.xlsx");
            workbook.write(out);
            out.flush();
            out.close();
            workbook.close();
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_SUCCESS);
            
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL,null);
        }
    }
    
    /**
     * 导出pdf文件，将前端信息（运营数据统计信息）通过POI导出到Excel中
     */
    @RequestMapping("/exportBusinessReportPDF")
    public Result exportBusinessReportPDF(HttpServletRequest request, HttpServletResponse response){
        try{
            //获取运营数据
            Map<String, Object> businessReport = reportService.getBusinessReport();
            //其中的套餐列表需要循环展示，使用JavaBean数据源方式填充
            List<Map> hotSetmeal = (List<Map>) businessReport.get("hotSetmeal");
            //模板文件
            String jrxmlPath = "D:\\myProject\\study9_health\\health_parent\\health_backend\\src" +
                    "\\main\\resources\\health_business3.jrxml";
            //编译后文佳
            String jasperPath = "D:\\myProject\\study9_health\\health_parent\\health_backend\\src" +
                    "\\main\\resources\\health_business3.jasper";
            //编译模板
            JasperCompileManager.compileReportToFile(jrxmlPath,jasperPath);
            
            //构造数据,就是上面查询的运营数据
            //填充数据，需要循环展示的，就是热门套餐,使用JavaBean数据源方式填充
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperPath, businessReport, new JRBeanCollectionDataSource(hotSetmeal));
    
            //输出文件，响应到前端，对话框形式下载/打开
            ServletOutputStream outputStream = response.getOutputStream();
            response.setContentType("application/pdf");
            response.setHeader("content-Disposition","attachment;fileName = myPdfa.pdf");
            //输出文件
            JasperExportManager.exportReportToPdfStream(jasperPrint,outputStream);
    
            /**报错：
             * java.lang.IllegalStateException:
             * org.springframework.web.HttpMediaTypeNotAcceptableException
             * 输出流关闭之后，socket也已经关闭，不能再次发送response，所以导致错误的就是return的返回值信息，
             * 这时候把return res;改成return null;就可以了，这样就不会因为需要返回信息而需要再次发送response
             */
            return null;
        }catch (Exception e){
            e.printStackTrace();
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL,null);
        }
    }
    
}
